home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / system / icpuid3a.zip / CPUID3.ASM next >
Assembly Source File  |  1994-01-04  |  18KB  |  543 lines

  1. ;       Filename:       cpuid32.msm
  2. ;
  3. ;       This program has been developed by Intel Corporation.  You have
  4. ;       Intel's permission to incorporate this source code into your
  5. ;       product royalty free.
  6. ;
  7. ;       Intel specifically disclaims all warranties, express or implied,
  8. ;       and all liability, including consequential and other indirect
  9. ;       damages, for the use of this code, including liability for
  10. ;       infringement of any proprietary rights.  Intel does not assume
  11. ;       any responsibility for any errors which may appear in this code
  12. ;       nor any responsibility to update it.
  13. ;
  14. ;       This program contains three parts:
  15. ;       Part 1: Identifies CPU type in the variable cpu_type:
  16. ;               0=8086 processor
  17. ;               2=Intel 286 processor
  18. ;               3=Intel386(TM) processor
  19. ;               4=Intel486(TM) processor
  20. ;               5=Pentium(TM) processor
  21. ;
  22. ;       Part 2: Identifies FPU type in the variable fpu_type:
  23. ;               0=FPU not present
  24. ;               1=FPU present
  25. ;               2=287 present (only if cpu_type=3)
  26. ;               3=387 present (only if cpu_type=3)
  27. ;
  28. ;       Part 3: Prints out the appropriate message.  This part can
  29. ;               be removed if this program is not used in a DOS-based
  30. ;               system.  Portions affected are at the end of the
  31. ;               data segment and the print procedure in the code
  32. ;               segment.
  33. ;
  34. ;       REVISION HISTORY:
  35. ;       Date:  4/93
  36. ;       1. Replaced the .486 with .186 to avoid generation of 0FH type long
  37. ;          conditional branches (such as the branch to end_get_cpuid at
  38. ;          the end of the 8086/8088 test, near code address 003D).  These
  39. ;          are not executable on the 8086/8088 and 80286, so the code falls
  40. ;          into some strange place and hangs the system.  The .186 also allows
  41. ;          multi-bit shifts to unpack CPUID info.  Using .186 requires 
  42. ;          that all 32-bit operand prefix (66H) be inserted by hand.  
  43. ;          This is done with a macro (OPND32).
  44. ;       2. Avoid all usage of 32-bit operands until it is clear that the
  45. ;          CPU is at least an 80386.  The use of the Exx registers caused 
  46. ;          the generation of the 66H prefix, which are not executed 
  47. ;          correctly on the 8086/8088 and 80286.  
  48. ;       3. Eliminated all the register save/restore and added comment 
  49. ;          that all registers are used by the functions.
  50. ;       4. Do the stack alignment just before messing with the AC bit in
  51. ;          EFLAGS, otherwise the stack may not be properly aligned.  Also
  52. ;          restore the AC bit immediately, so it does not stay set.
  53. ;       5. Changed the FPU detection to set one flag fpu_type (instead of
  54. ;          the previous two flags: fpu_present and infinity).  An fpu_type
  55. ;          of zero indicates no floating point unit is present, an fpu_type
  56. ;          of 2 indicates an 80287 is present, an fpu_type of 3 indicates
  57. ;          an 80387 is present.
  58. ;
  59. ;       If this code is assembled with MASM with no options specified, it
  60. ;       runs correctly on an 8086/8088, 80286, 80386, 80486, and 
  61. ;       Pentium(tm) processor.
  62. ;
  63.  
  64.  
  65.     TITLE   CPUID
  66.     DOSSEG
  67.     .model  small
  68.     .stack  100h
  69.     .186
  70.  
  71. OPND32 MACRO op_code, op_erand
  72.     db      66h     ; Force 32-bit operand size
  73.   IFNB <op_code>
  74.     db      op_code
  75.     IFNB <op_erand>
  76.     dd      op_erand; 32-bit immediate value
  77.     ENDIF
  78.   ENDIF
  79. ENDM
  80.  
  81. CPUID MACRO
  82.     db      0fh     ; Hardcoded opcode for CPUID instruction
  83.     db      0a2h
  84. ENDM
  85.  
  86. TRUE            equ     1
  87. FAMILY_MASK     equ     0f00h
  88. FAMILY_SHIFT    equ     8
  89. MODEL_MASK      equ     0f0h
  90. MODEL_SHIFT     equ     4
  91. STEPPING_MASK   equ     0fh
  92. FPU_FLAG        equ     1h
  93. MCE_FLAG        equ     80h
  94. CMPXCHG8B_FLAG  equ     100h
  95.  
  96.     .data
  97. fp_status       dw      ?
  98. vendor_id       db      12 dup (?)
  99. cpu_type        db      ?
  100. modell           db      ?
  101. stepping        db      ?
  102. id_flag         db      0
  103. fpu_type        db      0
  104. intel_proc      db      0
  105. feature_flags   dw      2 dup (0)
  106. ;
  107. ; remove the remaining data declarations if not using the DOS-based
  108. ; print procedure
  109. ;
  110. id_msg          db      "This system has a$"
  111. fp_8087         db      " and an 8087 math coprocessor$"
  112. fp_80287        db      " and an 80287 math coprocessor$"
  113. fp_80387        db      " and an 80387 math coprocessor$"
  114. c8086           db      "n 8086/8088 processor$"
  115. c286            db      "n 80286 processor$"
  116. c386            db      "n 80386 processor$"
  117. c486            db      "n 80486 DX processor or 80487 SX math coprocessor$"
  118. c486nfp         db      "n 80486 SX processor$"
  119. Intel486_msg    db      13,10,"This system contains a Genuine Intel486(TM) processor",13,10,"$"
  120. Pentium_msg     db      13,10,"This system contains a Genuine Intel Pentium(TM)  processor",13,10,"$"
  121. modelmsg        db      "Model:            $"
  122. steppingmsg     db      "Stepping:         $"
  123. familymsg       db      13,10,"Processor Family: $"
  124. period          db      ".",13,10,"$"
  125. dataCR          db      ?,13,10,"$"
  126. intel_id        db      "GenuineIntel"
  127. fpu_msg         db      13,10,"This processor contains a FPU",13,10,"$"
  128. mce_msg         db      "This processor supports the Machine Check Exception",13,10,"$"
  129. cmp_msg         db      "This processor supports the CMPXCHG8B instruction",13,10,"$"
  130. not_intel       db      "t least an 80486 processor.",13,10
  131.         db      "It does not contain a Genuine Intel part and as a result,",13,10
  132.         db      "the CPUID detection information cannot be determined at this time.",13,10,"$"
  133.  
  134. ;
  135. ;       The purpose of this code is to identify the processor and
  136. ;       coprocessor that is currently in the system.  The program first
  137. ;       determines the processor id.  When that is accomplished,
  138. ;       the program then determines whether a coprocessor
  139. ;       exists in the system.  If a coprocessor or integrated
  140. ;       coprocessor exists, the program identifies
  141. ;       the coprocessor id.  The program then prints out
  142. ;       the CPU and floating point presence and type.
  143. ;
  144.     .code
  145. start:  mov     ax, @data
  146.     mov     ds, ax          ; set segment register
  147.     mov     es, ax          ; set segment register
  148.     pushf                   ; save for restoration at end
  149.     call    get_cpuid
  150.     call    get_fpuid
  151.     call    print
  152.     popf
  153.     mov     ax, 4c00h       ; terminate program
  154.     int     21h
  155.  
  156.  
  157. get_cpuid proc
  158. ;
  159. ;       This procedure determines the type of CPU in a system
  160. ;       and sets the cpu_type variable with the appropriate
  161. ;       value.
  162. ;       All registers are used by this procedure, none are preserved.
  163.  
  164. ;       Intel 8086 CPU check
  165. ;       Bits 12-15 of the FLAGS register are always set on the
  166. ;       8086 processor.
  167. ;
  168. check_8086:
  169.     pushf                   ; push original FLAGS
  170.     pop     ax              ; get original FLAGS
  171.     mov     cx, ax          ; save original FLAGS
  172.     and     ax, 0fffh       ; clear bits 12-15 in FLAGS
  173.     push    ax              ; save new FLAGS value on stack
  174.     popf                    ; replace current FLAGS value
  175.     pushf                   ; get new FLAGS
  176.     pop     ax              ; store new FLAGS in AX
  177.     and     ax, 0f000h      ; if bits 12-15 are set, then CPU
  178.     cmp     ax, 0f000h      ;   is an 8086/8088
  179.     mov     cpu_type, 0     ; turn on 8086/8088 flag
  180.     jne     check_80286     ; jump if CPU is not 8086/8088
  181.     jmp     end_get_cpuid
  182. ;       Intel 286 CPU check
  183. ;       Bits 12-15 of the FLAGS register are always clear on the
  184. ;       Intel 286 processor in real-address mode.
  185. ;
  186. check_80286:
  187.     or      cx, 0f000h      ; try to set bits 12-15
  188.     push    cx              ; save new FLAGS value on stack
  189.     popf                    ; replace current FLAGS value
  190.     pushf                   ; get new FLAGS
  191.     pop     ax              ; store new FLAGS in AX
  192.     and     ax, 0f000h      ; if bits 12-15 clear, CPU=80286
  193.     mov     cpu_type, 2     ; turn on 80286 flag
  194.     jnz     check_80386     ; if no bits set, CPU is 80286
  195.     jmp     end_get_cpuid
  196. ;       Intel386 CPU check
  197. ;       The AC bit, bit #18, is a new bit introduced in the EFLAGS
  198. ;       regist